scene.t

documentation
#charset "us-ascii"
#include "advlite.h"


/*
 *   ****************************************************************************
 *    scene.t 
 *    This module forms an optional part of the adv3Lite library 
 *    (c) 2012-13 Eric Eve
 */

/* 
 *   The sceneManager object is used to control the scene-switching and
 *   execution mechanism.
 */
sceneManager: InitObject, Event
    execute()
    {
                
        /* 
         *   Set up a new Schedulable in the game to run our doScene method each
         *   turn
         */
       
        eventManager.schedulableList += self;
        
        /* 
         *   Run the executeEvent() method for the first time to set up any
         *   scenes that should be active at the start of play.
         */
//        executeEvent();
    }
    
    eventOrder = 200
    
    /* 
     *   Flagg: Do we want to allow the starting or ending of one Scene to trigger the starting or
     *   ending of another Scene. By default we do.
     */
    sameTurnTrigger = true
    
    /* 
     *   The maximum number of loops the do loop in executeEvent will go through before breaking
     *   out. This is to avoid getting into an infinite loop if Scenes are defined in a way that
     *   might otherwise cause them.
     */
    maxLoopCount = 10
    
    /* The executeEvent() method is run each turn to drive the Scenes mechanism */
    executeEvent()
    {       
        /* Check whether we have ended or started a Scene on this turn. */
        local sceneEnded = nil;
        local sceneStarted = nil;
        local loopCount = 0;
        
        /* 
         *   Keep track of all the Scenes we've called eachTurn() on so we don't it more than once
         *   on any given Scene.
         */
        local turnVec = new Vector;
        
        /* 
         *   We repeat the loop through all the Scenes in case starting or ending a Scene should
         *   tigger the start or end of another Scene.
         */
        do
        { 
            /* Increment the loop counter to check how many times we've been round this loop. */
            loopCount++;
            
            /* Check whether we have ended or started a Scene on this turn. */
            sceneEnded = nil;
            sceneStarted = nil;
            
           
            
            /* Go through each Scene defined in the game in turn. */
            for(local scene = firstObj(Scene); scene != nil ; scene = nextObj(scene,
                Scene))            
            {     
                
                
                /* 
                 *   If the scene's startsWhen condition is true and the scene is not already
                 *   happening, then provided it's a recurring scene or it's never been started
                 *   before, start the scene.
                 */
                if(scene.startsWhen && !scene.isHappening 
                   && (scene.recurring || scene.startedAt == nil))
                {
                    scene.start();
                    sceneStarted = true;
                }
                
                /*  
                 *   If the scene is happening and its endsWhen property is non-nil, then record the
                 *   value of its endsWhen property in its howEnded property and end the scene.
                 */
                if(scene.isHappening && (scene.howEnded = scene.endsWhen) != nil)
                {
                    scene.end();
                    sceneEnded = true;
                }
                
                /* 
                 *   If the scene is happening, call its eachTurn() method, unless we've alreasy
                 *   called it.
                 */
                if(scene.isHappening && turnVec.indexOf(scene) == nil)
                {
                    scene.eachTurn();
                    turnVec.appendUnique(scene);
                }
            }      
      
            /* 
             *   If a scene has started or ended we need to repeat going through all the Scenes in
             *   case this should trigger the stating or ending of another Scene
             */
        } while (sameTurnTrigger && (sceneEnded || sceneStarted) && loopCount <= maxLoopCount);
            
        if(loopCount >= maxLoopCount)
            "<.p><b>WARNING!</b> Potential infinite loop in one or more Scene definitions.<.p>";
            
    }
    
    execBeforeMe = [adv3LibInit]
    
    /* Run the beforeAction method on every currently active Scene */
    notifyBefore()
    {
        forEachInstance(Scene, function(scene) 
        {
            if(scene.isHappening)
                scene.beforeAction(); 
        });
}


notifyAfter()
{
    forEachInstance(Scene, function(scene) 
    {
        if(scene.isHappening)
            scene.afterAction(); 
    });
}
;


/* 
 *   A Scene is an object that represents a slice of time that starts and ends according to
 *   specified conditions, and which can define what happens when it starts and ends and also what
 *   happens each turn when it is happening.
 */
class Scene: object
    
    /* 
     *   An expression or method that evaluates to true when you want the scene to start
     */
    startsWhen = nil
    
    /*  
     *   an expression or method that evaluates to something other than nil when you want the scene
     *   to end
     */
    endsWhen = nil
    
    /* 
     *   Normally a scene will only occur once. Set recurring to true if you want the scene to start
     *   again every time its startsWhen condition is true.
     */
    recurring = nil
    
    /* 
     *   Is this scene currently taking place? (Game code should treat this as read-only)
     */
    isHappening = nil
    
    /* 
     *   Is this scene currently taking place? (Game code should treat this as
     *   read-only). We provide isActive as a read-only synonym of isHappening in
     *   case game code uses it on analogy with several other adv3Lite entities
     *   that do use an isActive property
     */
    isActive = isHappening
    
    /* The turn this scene started at */
    startedAt = nil
    
    /* The turn this scene ended at */
    endedAt = nil
    
    /* 
     *   The method executed when this Scene starts. Game code should normally
     *   override whenStarting() rather than this method.
     */
    start()
    {
        /* Note that this Scene is now happening */
        isHappening = true;
        
        /* Note the turn on which this Scene started */
        startedAt = libGlobal.totalTurns;
        
        /* 
         *   Execute our whenStarting() method to carry out the particular
         *   effects of this scene starting.
         */
        whenStarting();
    }
    
    /* 
     *   The method executed when this Scene ends. Game code should normally
     *   override whenStarting() rather than this method.
     */    
    end()
    {  
        /* 
         *   Execute our whenEnding method to carry out any particular effects
         *   of this scene coming to an end.
         */
        whenEnding();
        
        /* Note that this scene is no longer happening. */
        isHappening = nil;
        
        /* Note the turn on which this scene ended. */
        endedAt = libGlobal.totalTurns;       
        
        /* 
         *   Increment the counter of the number of times this scene has
         *   happened.
         */
        timesHappened++ ;        
    }
    
    /* Routine to execute when this scene starts */
    whenStarting() {}
    
    /* Routine to execute when this scene ends */
    whenEnding() {}
    
    /* Routine to execute every turn this scene is in progress. */
    eachTurn() {}
    
    /* Flag to show whether this scene has ever happened. */
    hasHappened = (endedAt != nil)
    
    /* The numbter of times this scene has happened. */
    timesHappened = 0
    
    /*  A user defined flag showing how the scene ended */
    howEnded = nil    
    
    /* 
     *   This method is called on every active Scene just before an action is
     *   about to take place. By default we do nothing here.
     */
    beforeAction() { }
    
    /* 
     *   This method is called on every active Scene just after an action has
     *   taken place. By default we do nothing here.
     */
    afterAction() { }
    
    /* 
     *   The number of turms this Scene has been active. Is this Scene is not happening, return -1.
     */
    turnsActive = (isHappening ? gTurns - startedAt : -1)
    
    
    /* 
     *   This method is called on each active scene before any Doers and can be used to
     *   conditionally rule out the action (by using abort or exit), for example if the player is
     *   character is tied up or otherwise incapacitated during the Scene. The lst parameter
     *   contains a list in the form [action, dobj, iobj] (or just [action] for an IAction or just
     *   [action, dobj]) and should be used to determine what the proposed action is.
     */ 
    
    preAction(lst) { }
    
    /* 
     *   Service method usede internally on the library to ensure that preAction() is called only on
     *   currently active scenes.
     */
    tryPreAction(lst)
    {
        if(isHappening)
            preAction(lst);
    }
;

Adv3Lite Library Reference Manual
Generated on 08/12/2025 from adv3Lite version 2.2.2